package com.wu.controller;


import com.alibaba.dubbo.config.annotation.Reference;
import com.wu.pojo.bean.PaperQuestionAddBean;
import com.wu.pojo.po.orgPo.OrgBase;
import com.wu.pojo.po.paperPo.Answer;
import com.wu.pojo.po.paperPo.Paper;
import com.wu.pojo.po.paperPo.Question;
import com.wu.pojo.res.Result;
import com.wu.pojo.dto.*;
import com.wu.service.*;
import com.wu.utils.CommonUtils;
import com.wu.utils.JwtUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.util.*;

import static cn.hutool.core.date.DateTime.now;
import static com.wu.constants.Constants.*;

/**
 * [问卷功能接口]
 *
 * @Author : [wuzhengru]
 * @Version : [v1.0]
 * @Date : [2021/4/17 23:41]
 */
@Slf4j
@RestController
@RequestMapping("/api/v1/admin/ques")
@Api(tags = "问卷功能接口", description = "PaperController")
public class PaperController {

    @Reference
    private OrgBaseService orgBaseService;
    @Reference
    private PaperService paperService;
    @Reference
    private QuestionService questionService;
    @Reference
    private AnswerService answerService;
    @Reference
    private ExcelService excelService;
    @Autowired
    private CommonUtils commonUtils;

    @RequiresRoles("admin")
    @RequiresAuthentication
    @ApiOperation("管理员获取问卷列表")
    @GetMapping("/admin/paperList")
    public Result paperListsByAdmin() {

        // 1、参数校验

        // 2、查询
        List<Paper> list = null;
        try {
            list = paperService.queryPaper();
        } catch (Exception e) {
            throw new RuntimeException("问卷列表获取失败！", e);
        }
        JSONArray jsonArray = new JSONArray();
        for (Paper paper : list) {// 遍历list
            // 获取问卷参与次数
            int totalCount = paperService.getPaperCount(paper.getPaperId());
            // 日期格式转换
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String crateDate = sdf.format(paper.getCreateTime());
            String startDate = null;
            String endDate = null;
            try {
                startDate = sdf.format(paper.getStartTime());
                endDate = sdf.format(paper.getEndTime());
            } catch (Exception e) {
                log.info("开始/截至时间未设置");
            }

            // 3、组装参数
            List<String> targets = new ArrayList<>();
            String target = paper.getTarget();
            if (null != target) {
                String[] split = target.split("#");
                targets.add(split[0]);
                targets.add(split[1]);
                targets.add(split[2]);
            }
            targets.forEach(System.out::println);

            JSONObject jsonObject = new JSONObject();
            jsonObject.put("paperId", paper.getPaperId());
            jsonObject.put("title", paper.getTitle());
            jsonObject.put("createTime", crateDate);
            jsonObject.put("startTime", startDate);
            jsonObject.put("endTime", endDate);
            jsonObject.put("status", paper.getStatus());
            jsonObject.put("totalCount", totalCount);
            jsonObject.put("adminName", paper.getAdminId());// 问卷创建者
            jsonObject.put("modelInfo", paper.getModelInfo());
            jsonObject.put("weightValue", paper.getWeightValue());

            jsonObject.put("target", targets);
            jsonArray.add(jsonObject);// 转换为数组
        }

        return Result.succ(jsonArray);
    }

    @RequiresRoles("user")
    @RequiresAuthentication
    @ApiOperation("企业用户获取问卷列表")
    @GetMapping("/user/paperList")
    public Result paperListsByUser(@RequestParam String token) {

        // 1、初始化参数
        List<Paper> listByCondition = new ArrayList<>();// 满足调查条件列表

        String orgAddrTemp = null;// 数据库区域
        String busiTypeTemp = null;// 数据库行业
        String orgTypeTemp = null;// 数据库类型

        // 获取用户id、上属机构
        String userId = null;
        try {
            userId = (String)JwtUtils.getClaimByToken(token).get("userId");
        } catch (Exception e) {
            log.debug("token信息失效,userId提取失败",e);
            return Result.fail("token信息失效，请重新登录！");
        }
        OrgBase orgBase = orgBaseService.queryOrgByUserId(userId);

        // 拿到用户区域、行业、类型
        String orgAddr = null;
        String busiType = null;
        String orgType = null;
        try {
            orgAddr = orgBase.getOrgAddr();
            busiType = orgBase.getBusiType();
            orgType = orgBase.getOrgType();
        } catch (Exception e) {
            log.error("用户信息缺失");
            return Result.fail("该用户信息缺失");
        }

        List<Paper> list = paperService.queryPaperWithStatus1();// 获取全部发布中问卷列表
        for (Paper paper : list) {

            boolean isOrgAddr = false;// 区域判断标志
            boolean isBusiType = false;// 行业判断标志
            boolean isOrgType = false;// 类型判断标志
            String target = paper.getTarget();

            if (target != null) { // target拆分赋值
                String[] split = target.split("#");
                orgAddrTemp = split[0];
                busiTypeTemp = split[1];
                orgTypeTemp = split[2];
                // 依次判断，查看面向该企业问卷
                if (orgAddr.equals(orgAddrTemp) || "-".equals(orgAddrTemp)) {
                    isOrgAddr = true;
                }
                if (busiType.equals(busiTypeTemp) || "-".equals(busiTypeTemp)) {
                    isBusiType = true;
                }
                if (orgType.equals(orgTypeTemp) || "-".equals(orgTypeTemp)) {
                    isOrgType = true;
                }
                if (!(isOrgAddr && isBusiType && isOrgType)) { // 只要有一个不为真就不满足条件
                    continue; // 跳过此问卷
                }
            }
            // 满足限制条件
            listByCondition.add(paper);
        }

        JSONArray jsonArray = new JSONArray();
        for (Paper paper : listByCondition) { // 遍历面向该用户的问卷
            // 获取问卷是否已答过
            List<Answer> answers = answerService.queryAnswerByPaperIdAndUserId(paper.getPaperId(), userId);
            String flag = UNCOMPLETE;
            if (answers.size() > 0) { // 判断是否已完成此问卷
                flag = COMPLETE;
            }

            // 日期格式转换
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String startDate = null;
            String endDate = null;
            try {
                startDate = sdf.format(paper.getStartTime());
                endDate = sdf.format(paper.getEndTime());
            } catch (Exception e) {
                log.debug("开始/截至时间未设置");
            }

            // 3、组装参数
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("paperId", paper.getPaperId());
            jsonObject.put("title", paper.getTitle());
            jsonObject.put("startTime", startDate);
            jsonObject.put("endTime", endDate);
            jsonObject.put("status", paper.getStatus());
            jsonObject.put("completeFlag", flag);
            jsonObject.put("target", paper.getTarget());
            jsonArray.add(jsonObject);// 转换为数组
        }

        return Result.succ(jsonArray);
    }

    @RequiresRoles(value={"admin","user"},logical = Logical.OR)
    @RequiresAuthentication
    @ApiOperation("模糊查询问卷")
    @PostMapping("fuzzyQuery")
    public Result fuzzyQuery(@RequestBody Paper paperInfo, BindingResult result) {
        // 1、参数校验
        Result res = Commonts.getErrors(result);
        if (!(null == res || "".equals(res))) {// return校验错误
            return Commonts.getErrors(result);
        }

        // 2、查询问卷列表
        List<Paper> papers = paperService.fuzzyQuery(paperInfo);

        // 3、组装参数
        JSONArray jsonArray = new JSONArray();
        for (Paper paper : papers) {// 循环列表

            // 获取问卷参与次数
            int totalCount = paperService.getPaperCount(paper.getPaperId());

            JSONObject jsonObject = new JSONObject();
            jsonObject.put("paperId", paper.getPaperId());
            jsonObject.put("title", paper.getTitle());
            jsonObject.put("totalCount", totalCount);
            jsonObject.put("status", paper.getStatus());
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
            String createTime = formatter.format(paper.getCreateTime());
            String startTime = null;
            String endTime = null;
            try {
                startTime = formatter.format(paper.getStartTime());
                endTime = formatter.format(paper.getEndTime());
            } catch (Exception e) {
                log.debug("未设置起始/终止时间");
            }
            jsonObject.put("createTime", createTime);
            jsonObject.put("startTime", startTime);
            jsonObject.put("endTime", endTime);
            // 问卷创建者
            jsonObject.put("adminName", paper.getAdminId());
            jsonObject.put("modelInfo", paper.getModelInfo());// 运算模型
            jsonObject.put("weightValue", paper.getWeightValue());// 权重值
            jsonArray.add(jsonObject);
        }
        return Result.succ(jsonArray);
    }

    @RequiresRoles(value={"admin","user"},logical = Logical.OR)
    @RequiresAuthentication
    @ApiOperation("查看问卷数据")
    @PostMapping("paperData")
    public Result getPaperData(@RequestBody PaperDTO paperDTO, BindingResult result) throws Exception {

        // 1、参数校验
        Result res = Commonts.getErrors(result);
        if (!(null == res || "".equals(res))) {// return校验错误
            return Commonts.getErrors(result);
        }
        Paper paper = paperService.queryPaperByID(paperDTO.getPaperId());
        if (null == paper) {
            return Result.fail("要查看data的id无效");
        }

        String msg = null;// 问卷状态
        if (paper.getStatus().equals(STATUS_UNRELEASE)) {
            msg = "问卷未发布";
        } else if (paper.getStatus().equals(STATUS_RELEASE)) {
            msg = "问卷发布中";
        } else if (paper.getStatus().equals(STATUS_END)) {
            msg = "问卷调查已结束";
        } else if (paper.getStatus().equals(STATUS_DELETE)) {
            msg = "问卷删除至回收站";
        }

        // 获取用户id
        String token = paperDTO.getToken();
        String userId = null;
        if (null != token) { // 用户入口
            try {
                userId = (String)JwtUtils.getClaimByToken(token).get("userId");
            } catch (Exception e) {
                log.debug("token信息失效,userId提取失败",e);
                return Result.fail("token信息失效，请重新登录！");
            }
        }
        // 2、获取数据
        Object questionData = paperService.getQuestionData(paperDTO.getPaperId(), userId, null);
        return Result.succ(msg, questionData);

    }

    @RequiresRoles("admin")
    @RequiresAuthentication
    @ApiOperation("新增问卷")
    @PostMapping("paper")
    public Result addPaper(@RequestBody PaperAddDTO paper, BindingResult result) {

        // 1、参数验证
        Result res = Commonts.getErrors(result);
        if (!(null == res || "".equals(res))) {// return校验错误
            return Commonts.getErrors(result);
        }

        List<Paper> paperList = paperService.fuzzyQuery(new Paper().setTitle(paper.getTitle()));
        if (null != paperList && paperList.size() > 0) { // 判断重复性
            return Result.fail("此问卷已存在，请勿重复提交");
        }

        for (PaperQuestionAddBean paperQuestionAdd : paper.getQuestions()) {
            if (COMPLETION.equals(paperQuestionAdd.getQuestionType())) {// 简答题置空
                for (Object o : paperQuestionAdd.getQuestionOption()) {
                    String option = o + "";
                    if (option.length() > 8) { // {value=}
                        return Result.fail("简答题选项应置空");
                    }
                }
            } else {
                for (Object o : paperQuestionAdd.getQuestionOption()) {
                    String option = o + "";
                    if (option.length() == 8) { // {value=}
                        return Result.fail("选项内容不能为空");
                    }
                }
            }
        }

        // 2、参数组装
        Paper newPaper = paper.paperInit();// 问卷参数
        newPaper.setPaperId(CommonUtils.getUUID());// paperId
        newPaper.setAdminId(CommonUtils.getUUID());// 管理员id
        newPaper.setStartTime(commonUtils.getDateByDateString(paper.getStartTime()));
        newPaper.setEndTime(commonUtils.getDateByDateString(paper.getEndTime()));

        List<Question> questionList = new ArrayList<>();
        for (PaperQuestionAddBean ques : paper.getQuestions()) {// 组装问题列表

            // 转换格式
            List<HashMap<String, String>> questionOption = (List<HashMap<String, String>>) (List) ques.getQuestionOption();

            // 拼装选项，统一格式
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("[");
            if (!ques.getQuestionType().equals("3")) { // 非简答题，简单题只需拼装[]
                if (!(questionOption.size() > 0)) {
                    return Result.fail(String.format("第%s题未设置选项，请完善后提交", ques.getQuestionNo()));
                }
                for (int i = 0; i < questionOption.size(); i++) {
                    stringBuilder.append("\"");
                    stringBuilder.append(questionOption.get(i).get("value")); // 前端传入类型为linkMap
                    stringBuilder.append("\"");
                    if (i < questionOption.size() - 1) {
                        stringBuilder.append(",");
                    }
                }
            }
            stringBuilder.append("]");

            Question question = ques.questionInit()
                    .setId(CommonUtils.getUUID())
                    .setPaperId(newPaper.getPaperId())
                    .setQuestionOption(stringBuilder.toString());// 初始化题目
            questionList.add(question);
        }

        // 3、数据入库
        newPaper.setStatus(STATUS_RELEASE);// 默认开启状态
        paperService.insertPaper(newPaper);// 问卷入库
        questionService.insertQuestion(questionList);// 问题批量入库
        String excelFile = excelService.createExcelFile(newPaper.getPaperId(),newPaper.getTitle());// 生成EXCEL，路径入库
// ==================以后优化,事务需添加到service
        return Result.succ("添加问卷成功",excelFile);
    }

    @RequiresRoles("admin")
    @RequiresAuthentication
    @ApiOperation("更新单个问卷")
    @PutMapping("paper")
    public Result updatePaper(@RequestBody PaperUpdateDTO paperDto, BindingResult result) {

        // 1、参数校验
        Result res = Commonts.getErrors(result);
        if (!(null == res || "".equals(res))) {// return校验错误
            return Commonts.getErrors(result);
        }

        try {
            Paper paper = paperService.queryPaperByID(paperDto.getPaperId());
            if (paper.getEndTime().before(now())) {
                log.info("问卷 [{}] 为往期问卷，更改操作失败！", paper.getTitle());
                return Result.fail(412, String.format("该问卷为往期问卷，发布操作失败！", paper.getTitle()), null);
            }
        } catch (Exception e) {
            log.info("此问卷截至时间为空");
        }

        // 2、拼装调查对象参数
        List<String> targets = paperDto.getTarget();
        StringBuilder target = new StringBuilder();
        if (null == targets || targets.isEmpty()) { // 传入空，设置默认值
            target.append("-#-#-");
        } else {
            for (int i = 0; i < targets.size(); i++) { // 拼装字符串 区域#行业#类型
                target.append(targets.get(i));
                if (i == targets.size() - 1) { // 最后不加#
                    continue;
                }
                target.append("#");
            }
        }

        // 3、更新入库
        paperService.updatePaper(new Paper().setPaperId(paperDto.getPaperId()).setStatus(paperDto.getStatus())
                .setModelInfo(paperDto.getModelInfo()).setWeightValue(paperDto.getWeightValue())
                .setTarget(target.toString()));

        return Result.succ("更新成功");
    }

    @RequiresRoles("admin")
    @RequiresAuthentication
    @ApiOperation("批量更新问卷状态")
    @PutMapping("papers")
    public Result updatePapers(@RequestBody PaperUpdateDTO paperDto) {

        // 1、参数校验
        if (paperDto.getStatus() == null || "".equals(paperDto.getStatus())) {
            return Result.fail("批量更新失败，无更新状态！");
        }

        if (paperDto.getPaperIds() == null || paperDto.getPaperIds().isEmpty()) {
            return Result.fail("请选择问卷！");
        }

        List<String> paperIds = paperDto.getPaperIds();
        for (String paperId : paperIds) { // 时间校验
            // endTime必须大于等于当前时间
            Paper paper = null;
            try {
                paper = paperService.queryPaperByID(paperId);
                if (paper.getEndTime().before(now())) {
                    log.info("问卷 [{}] 为往期问卷，无法重新发布！", paper.getTitle());
                    return Result.fail(412, String.format("问卷 [%s] 为往期问卷，无法重新发布！", paper.getTitle()), null);
                }
            } catch (Exception e) {
            }
        }

        // 2、更新入库
        paperService.updatePapers(paperIds, paperDto.getStatus()); // 批量更新

        return Result.succ("批量更新成功");
    }

    @RequiresRoles("admin")
    @RequiresAuthentication
    @ApiOperation("删除问卷")
    @PostMapping("deletePaper")
    public Result deletePaper(@RequestBody PaperDeleteDTO paperDeleteDTO, BindingResult result) {

        // 1、参数校验
        Result res = Commonts.getErrors(result);
        if (!(null == res || "".equals(res))) {// return校验错误
            return Commonts.getErrors(result);
        }
        // 验证重复性
        if (paperDeleteDTO.getFlag().equals(DELETE)) { // 粉碎
            for (String paperId : paperDeleteDTO.getPaperIds()) {
                if (null == paperService.fuzzyQuery(new Paper().setPaperId(paperId).setStatus(STATUS_DELETE))
                        || paperService.fuzzyQuery(new Paper().setPaperId(paperId).setStatus(STATUS_DELETE)).size() == 0) {
                    log.info("问卷id:\"{}\"不存在", paperId);
                    return Result.fail("问卷不存在，请勿重复操作");
                }
            }
        } else {
            for (String paperId : paperDeleteDTO.getPaperIds()) {// 普通删除
                if (null != paperService.fuzzyQuery(new Paper().setPaperId(paperId).setStatus(STATUS_DELETE))
                        && paperService.fuzzyQuery(new Paper().setPaperId(paperId).setStatus(STATUS_DELETE)).size() > 0) {
                    log.info("问卷id:\"{}\"不存在", paperId);
                    return Result.fail("问卷不存在，请勿重复操作");
                }
            }
        }

        // 2、批量删除
        paperService.deleteManyPapers(paperDeleteDTO);

        return Result.succ("删除成功");
    }

    @RequiresRoles("admin")
    @RequiresAuthentication
    @ApiOperation("还原问卷")
    @PostMapping("resPaper")
    public Result resManyPapers(@RequestBody PaperDeleteDTO paperDeleteDTO, BindingResult result) {

        // 1、参数校验
        Result res = Commonts.getErrors(result);
        if (!(null == res || "".equals(res))) {// return校验错误
            return Commonts.getErrors(result);
        }

        for (String paperId : paperDeleteDTO.getPaperIds()) {// 验证重复性
            List<Paper> papers = paperService.fuzzyQuery(new Paper().setPaperId(paperId).setStatus(STATUS_DELETE));
            if (null == papers || papers.isEmpty()) {
                log.info("问卷id:\"{}\"不存在", paperId);
                return Result.fail("问卷不存在，请勿重复操作");
            }
        }

        // 2、批量还原
        paperService.resManyPapers(paperDeleteDTO);

        return Result.succ("问卷还原成功");
    }

    @RequiresRoles("admin")
    @RequiresAuthentication
    @ApiOperation("清空回收站问卷")
    @GetMapping("deleteAll")
    public Result deleteAll() {

        // 清空回收站
        paperService.deleteAll();

        return Result.succ("回收站已清空");
    }

}